“Conceitos Estatísticos para IA”
Prof. Adelaide Alves de Oliveira
- TURMA: FIAP-06IA
- EDUARDO MORARES
- EDUARDO SIQUEIRA DE LIMA
- GABRIEL SHIKAMA
- RICARDO KALIMANIS
Inicicalmente vamos instalar os pacotes, caso seja necessário, que serão usados no decorrer da análise
#ignorando alertas para não poluir a exibição do markdwon
options(warn =-1)
#lista de pacotes que iremos utilizar no projeto
Pacotes_Necessarios <- c("ggplot2","readr","dplyr", "corrgram","corrplot", "plotly","skimr","gridExtra","GGally","ggpubr")
#com base nos pacotes instalados crio uma variavel somente com os pacotes que não temos ainda para realizar a instalação
#dos pacotes que de fato não possuimos
PacotesNovos <- Pacotes_Necessarios[!(Pacotes_Necessarios %in% installed.packages()[,"Package"])]
if(length(PacotesNovos)){ install.packages(PacotesNovos)} else {print("Todos os Pacotes Estão Instalados")}
[1] "Todos os Pacotes Estão Instalados"
Carregando todas as as Bibliotecas mencionadas no passo anterior
lapply(Pacotes_Necessarios, require, character.only = TRUE)
Importando os Datasets de Wines Quality.
Lista DE - PARA das colunas
| ID |
ID (que não sera utilizado) |
| fixed acidity |
acidez_fixa |
| volatile acidity |
acidez_volatil |
| citric acid |
acido_citrico |
| residual sugar |
acucar_residual |
| chlorides |
cloretos |
| free sulfur dioxide |
fsd |
| total sulfur dioxide |
tsd |
| density |
densidade |
| pH |
PH |
| sulphates |
sulfatos |
| alcohol |
grau_alcolico |
| quality |
qualidade |
| Vinho |
Tipo |
#Criando uma variável nome_colunas que receberá os nomes das colunas que normalizaremos a fim de facilitar o resto da análise
nome_colunas <- c("id","acidez_fixa","acidez_volatil","acido_citrico","acucar_residual","cloretos", "fsd", "tsd","densidade","PH", "sulfatos","grau_alcolico","qualidade","tipo")
#uso da biblioteca readr é para obter uma performance de carga melhor que a lib padrão do R
#e escolhemos o read_csv2 justamente pelo fato do arquivo estar separado por ; ao invés de ,
#o separador decimal também não é o . que é convencional e este comando ja os converte facilmente
#skip = 1 para ignorar o cabecalho que mudamos para melhor entendimento
vinhos <- read_csv2("./DataSets/BaseWine_Red_e_White.csv" ,col_names = nome_colunas, skip = 1)
Adicionando uma classificação de bom ou ruim de acordo com sua nota, onde menor que 5 é ruim até 7 bom e acima disso excelente
#converte tipo paara fator
vinhos$tipo <- factor(vinhos$tipo, ordered = T)
#Criando uma coluna de Ranking para dizer o quão bom é o vinho
vinhos$rating <- factor(ifelse(vinhos$qualidade <= 5, 'Ruim', ifelse(vinhos$qualidade <= 7, 'Bom', 'Excelente')))
Exibindo os dados das dimensões, sumário, estrutura e as primeiras linhas do DataFrame Vinhos
attach(vinhos)
skim(vinhos[, names(vinhos) != "id"] )
Skim summary statistics
n obs: 6497
n variables: 14
-- Variable type:factor --------------------------------------------------------
variable missing complete n n_unique top_counts ordered
rating 0 6497 6497 3 Bom: 3915, Rui: 2384, Exc: 198, NA: 0 FALSE
tipo 0 6497 6497 2 WHI: 4898, RED: 1599, NA: 0 TRUE
-- Variable type:numeric -------------------------------------------------------
variable missing complete n mean sd p0 p25 p50 p75 p100 hist
acidez_fixa 0 6497 6497 7.22 1.3 3.8 6.4 7 7.7 15.9 ▁▇▇▂▁▁▁▁
acidez_volatil 0 6497 6497 0.34 0.16 0.08 0.23 0.29 0.4 1.58 ▇▇▂▁▁▁▁▁
acido_citrico 0 6497 6497 0.32 0.15 0 0.25 0.31 0.39 1.66 ▂▇▂▁▁▁▁▁
acucar_residual 0 6497 6497 5.44 4.73 0.6 1.8 3 8.1 45.8 ▇▂▂▁▁▁▁▁
cloretos 0 6497 6497 0.056 0.035 0.009 0.038 0.047 0.065 0.61 ▇▁▁▁▁▁▁▁
densidade 0 6497 6497 0.99 0.003 0.99 0.99 0.99 1 1.01 ▂▇▇▅▁▁▁▁
fsd 0 6497 6497 30.53 17.75 1 17 29 41 289 ▇▃▁▁▁▁▁▁
grau_alcolico 0 6497 6497 10.49 1.22 0.96 9.5 10.3 11.3 14.9 ▁▁▁▁▆▇▃▁
PH 0 6497 6497 3.22 0.16 2.72 3.11 3.21 3.32 4.01 ▁▃▇▇▃▁▁▁
qualidade 0 6497 6497 5.82 0.87 3 5 6 6 9 ▁▁▆▇▁▃▁▁
sulfatos 0 6497 6497 0.53 0.15 0.22 0.43 0.51 0.6 2 ▅▇▂▁▁▁▁▁
tsd 0 6497 6497 115.74 56.52 6 77 118 156 440 ▅▆▇▃▁▁▁▁
Observa-se que:
- O campo
acucar_residual e fsd possuem um desvio padrão acima das demais variaveis
- A maioria dos histogramas apresenta uma distribuição normal entretanto não centralizado o que pode indicar a presença de outliers
Verificando valores nulos
sapply(vinhos, function(x)all(is.na(x)))
Error in lapply(X = X, FUN = FUN, ...) : object 'vinhos' not found
O resultado acima nos descreve que não há presença de nulos na base, isto é indicado pelo retorno FALSE em cada variável
Podemos observar que apesar do desenho ser similar à uma distribuição normal, isso se deu pois mais à esquerda exceto grau alcoolico, que se sabe que não há vinhos com teor alcoolico abaixo de 6.5% (levendo em consideração um vinho de sobremesa mais licoroso). portanto nosso proximo objeto de estudo será o grau alcoolico a procura de outliers e a remoção dos mesmos.
O comando aplicado para todos atributos abaixo exibição dos box-plot abaixo foi:
boxplot(Column_Name, col=“slategray2”, pch=19)
mtext(“Titulo” , cex=0.8, side=1, line=2)


Outliers
Nota se que quase todas as variáveis possuem outliers e para uma melhor acurácia no modelo iremos removê-las da análise. O Metodo mais indicado para remoção dos outliers é amplitude interquartil (IQR - InterQuantile Range) onde: *IQR = Q3(quartil 3) - Q1(quartil 1) Com o IQR calculado é necessário definir o limite inferior e superior que é dado pela seguinte formula:
\[Lim_{Sup} = \bar{X} + 1,5 * IQR\]
\[Lim_{Inf} = \bar{X} - 1,5 * IQR\]
Para elucidar a aplicação do método vamos analisar a variavel “Acidez Fixa” notamos que há muitos valores acima do Q3 a uns poucos abaixo de Q1, Oserve o sumário desta variavel

De modo que a remoção dos outliers fez com que a distribuição dos dados ficasse mais homogênea como demonstro nos histrogramas a seguir
#comparando os resultados
par(mfrow=c(1,2), oma = c(1,1,0,0) + 0.1, mar = c(3,3,1,1) + 0.1)
hist(acidez_fixa, col="slategray2", main = "")
mtext("Antes" , cex=0.8, side=1, line=2)
hist(Vinhos_Normalizado$acidez_fixa, col="slategray2", main = "")
mtext("Depois" , cex=0.8, side=1, line=2)

Para automatizar o processo de analise e remoção dos outliers criamos uma função para executar essa tarefa, e segue:
vinhos_final$acidez_fixa <- remove_outliers(acidez_fixa, T)
Examinando os dados pos limpeza dos outliers
LS0tDQp0aXRsZTogIkFOQUxJU0UgRE8gREFUQVNFVCBXSU5FIFFVQUxJVFkiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyMgICoqIkNvbmNlaXRvcyBFc3RhdMOtc3RpY29zIHBhcmEgSUEiKiogIA0KIyMjIyAgKlByb2YuIEFkZWxhaWRlIEFsdmVzIGRlIE9saXZlaXJhKg0KDQo8YnIvPg0KDQoqIFRVUk1BOiBGSUFQLTA2SUENCiAgKyBFRFVBUkRPIE1PUkFSRVMNCiAgKyBFRFVBUkRPIFNJUVVFSVJBIERFIExJTUENCiAgKyBHQUJSSUVMIFNISUtBTUENCiAgKyBSSUNBUkRPIEtBTElNQU5JUw0KDQo8YnIvPjxici8+DQpJbmljaWNhbG1lbnRlIHZhbW9zIGluc3RhbGFyIG9zIHBhY290ZXMsIGNhc28gc2VqYSBuZWNlc3PDoXJpbywgcXVlIHNlcsOjbyB1c2Fkb3Mgbm8gZGVjb3JyZXIgZGEgYW7DoWxpc2UNCmBgYHtyfQ0KDQojaWdub3JhbmRvIGFsZXJ0YXMgcGFyYSBuw6NvIHBvbHVpciBhIGV4aWJpw6fDo28gZG8gbWFya2R3b24NCm9wdGlvbnMod2FybiA9LTEpDQoNCiNsaXN0YSBkZSBwYWNvdGVzIHF1ZSBpcmVtb3MgdXRpbGl6YXIgbm8gcHJvamV0bw0KUGFjb3Rlc19OZWNlc3NhcmlvcyA8LSBjKCJnZ3Bsb3QyIiwicmVhZHIiLCJkcGx5ciIsICJjb3JyZ3JhbSIsImNvcnJwbG90IiwgInBsb3RseSIsInNraW1yIiwiZ3JpZEV4dHJhIiwiR0dhbGx5IiwiZ21vZGVscyIpDQoNCiNjb20gYmFzZSBub3MgcGFjb3RlcyBpbnN0YWxhZG9zIGNyaW8gdW1hIHZhcmlhdmVsIHNvbWVudGUgY29tIG9zIHBhY290ZXMgcXVlIG7Do28gdGVtb3MgYWluZGEgcGFyYSByZWFsaXphciBhIGluc3RhbGHDp8OjbyANCiNkb3MgcGFjb3RlcyBxdWUgZGUgZmF0byBuw6NvIHBvc3N1aW1vcw0KUGFjb3Rlc05vdm9zIDwtIFBhY290ZXNfTmVjZXNzYXJpb3NbIShQYWNvdGVzX05lY2Vzc2FyaW9zICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKClbLCJQYWNrYWdlIl0pXQ0KaWYobGVuZ3RoKFBhY290ZXNOb3ZvcykpeyBpbnN0YWxsLnBhY2thZ2VzKFBhY290ZXNOb3Zvcyl9IGVsc2Uge3ByaW50KCJUb2RvcyBvcyBQYWNvdGVzIEVzdMOjbyBJbnN0YWxhZG9zIil9DQoNCmBgYA0KDQoNCg0KQ2FycmVnYW5kbyB0b2RhcyBhcyBhcyBCaWJsaW90ZWNhcyBtZW5jaW9uYWRhcyBubyBwYXNzbyBhbnRlcmlvcg0KYGBge3IsIHJlc3VsdHM9ImhpZGUifQ0KbGFwcGx5KFBhY290ZXNfTmVjZXNzYXJpb3MsIHJlcXVpcmUsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkNCmBgYA0KDQoNCg0KSW1wb3J0YW5kbyBvcyBEYXRhc2V0cyBkZSBXaW5lcyBRdWFsaXR5Lg0KDQoNCiMjIyMgTGlzdGEgREUgLSBQQVJBIGRhcyBjb2x1bmFzDQoNCg0KDQpOb21lIG5vIEFycXVpdm8gICAgIHwgIE5vbWUgVHJhZHV6aWRvDQotLS0tLS0tLS0tLS0tLS0tICAgIHwtLS0tLS0tLS0tLS0tLS0tLQ0KSUQgICAgICAgICAgICAgICAgICB8SUQgKHF1ZSBuw6NvIHNlcmEgdXRpbGl6YWRvKQ0KZml4ZWQgYWNpZGl0eSAgICAgICB8YWNpZGV6X2ZpeGENCnZvbGF0aWxlIGFjaWRpdHkgICAgfGFjaWRlel92b2xhdGlsDQpjaXRyaWMgYWNpZCAgICAgICAgIHxhY2lkb19jaXRyaWNvCQ0KcmVzaWR1YWwgc3VnYXIgICAgICB8YWN1Y2FyX3Jlc2lkdWFsDQpjaGxvcmlkZXMgICAgICAgICAgIHxjbG9yZXRvcw0KZnJlZSBzdWxmdXIgZGlveGlkZSB8ZnNkDQp0b3RhbCBzdWxmdXIgZGlveGlkZXx0c2QNCmRlbnNpdHkgICAgICAgICAgICAgfGRlbnNpZGFkZQ0KcEggICAgICAgICAgICAgICAgICB8UEgNCnN1bHBoYXRlcyAgICAgICAgICAgfHN1bGZhdG9zDQphbGNvaG9sICAgICAgICAgICAgIHxncmF1X2FsY29saWNvDQpxdWFsaXR5ICAgICAgICAgICAgIHxxdWFsaWRhZGUNClZpbmhvICAgICAgICAgICAgICAgfFRpcG8NCg0KDQpgYGB7ciwgcmVzdWx0cz0iaGlkZSJ9DQoNCiNDcmlhbmRvIHVtYSB2YXJpw6F2ZWwgbm9tZV9jb2x1bmFzIHF1ZSByZWNlYmVyw6Egb3Mgbm9tZXMgZGFzIGNvbHVuYXMgcXVlIG5vcm1hbGl6YXJlbW9zIGEgZmltIGRlIGZhY2lsaXRhciBvIHJlc3RvIGRhIGFuw6FsaXNlDQpub21lX2NvbHVuYXMgPC0gYygiaWQiLCJhY2lkZXpfZml4YSIsImFjaWRlel92b2xhdGlsIiwiYWNpZG9fY2l0cmljbyIsImFjdWNhcl9yZXNpZHVhbCIsImNsb3JldG9zIiwgImZzZCIsICJ0c2QiLCJkZW5zaWRhZGUiLCJQSCIsICJzdWxmYXRvcyIsImdyYXVfYWxjb2xpY28iLCJxdWFsaWRhZGUiLCJ0aXBvIikNCg0KI3VzbyBkYSBiaWJsaW90ZWNhIHJlYWRyIMOpIHBhcmEgb2J0ZXIgdW1hIHBlcmZvcm1hbmNlIGRlIGNhcmdhIG1lbGhvciBxdWUgYSBsaWIgcGFkcsOjbyBkbyBSDQojZSBlc2NvbGhlbW9zIG8gcmVhZF9jc3YyIGp1c3RhbWVudGUgcGVsbyBmYXRvIGRvIGFycXVpdm8gZXN0YXIgc2VwYXJhZG8gcG9yIDsgYW8gaW52w6lzIGRlICwNCiNvIHNlcGFyYWRvciBkZWNpbWFsIHRhbWLDqW0gbsOjbyDDqSBvIC4gcXVlIMOpIGNvbnZlbmNpb25hbCBlIGVzdGUgY29tYW5kbyBqYSBvcyBjb252ZXJ0ZSBmYWNpbG1lbnRlDQojc2tpcCA9IDEgcGFyYSBpZ25vcmFyIG8gY2FiZWNhbGhvIHF1ZSBtdWRhbW9zIHBhcmEgbWVsaG9yIGVudGVuZGltZW50bw0KdmluaG9zIDwtIHJlYWRfY3N2MigiLi9EYXRhU2V0cy9CYXNlV2luZV9SZWRfZV9XaGl0ZS5jc3YiICxjb2xfbmFtZXMgPSBub21lX2NvbHVuYXMsIHNraXAgPSAxKQ0KDQoNCmBgYA0KDQoNCkFkaWNpb25hbmRvIHVtYSBjbGFzc2lmaWNhw6fDo28gZGUgYm9tIG91IHJ1aW0gZGUgYWNvcmRvIGNvbSBzdWEgbm90YSwgb25kZSBtZW5vciBxdWUgNSDDqSBydWltIGF0w6kgNyBib20gZSBhY2ltYSBkaXNzbyBleGNlbGVudGUNCg0KYGBge3J9DQoNCiNjb252ZXJ0ZSB0aXBvIHBhYXJhIGZhdG9yDQp2aW5ob3MkdGlwbyA8LSBmYWN0b3IodmluaG9zJHRpcG8sIG9yZGVyZWQgPSBUKQ0KDQojQ3JpYW5kbyB1bWEgY29sdW5hIGRlIFJhbmtpbmcgcGFyYSBkaXplciBvIHF1w6NvIGJvbSDDqSBvIHZpbmhvDQp2aW5ob3MkcmF0aW5nIDwtIGZhY3RvcihpZmVsc2UodmluaG9zJHF1YWxpZGFkZSA8PSA1LCAnUnVpbScsIGlmZWxzZSh2aW5ob3MkcXVhbGlkYWRlIDw9IDcsICdCb20nLCAnRXhjZWxlbnRlJykpKQ0KDQpgYGANCg0KDQoNCkV4aWJpbmRvIG9zIGRhZG9zIGRhcyBkaW1lbnPDtWVzLCBzdW3DoXJpbywgZXN0cnV0dXJhIGUgYXMgcHJpbWVpcmFzIGxpbmhhcyBkbyBEYXRhRnJhbWUgVmluaG9zDQoNCmBgYHtyICxyZXN1bHRzPSJoaWRlIn0NCg0KYXR0YWNoKHZpbmhvcykNCg0KYGBgDQoNCmBgYHtyfQ0KI2RlbW9uc3RyYW5kbyBhcyBxdWFudGlkYWRlcyBkZSBkaW1lbnNvZXMgZGUgYW1ib3MgZGF0YXNldHMNCg0KZGltKHZpbmhvcykNCnNraW0odmluaG9zWywgbmFtZXModmluaG9zKSAhPSAiaWQiXSApICNyZXRpcmFuZG8gYSBjb2x1bmEgSUQgZGEgYW7DoWxpc2UNCnN0cih2aW5ob3MpDQpoZWFkICh2aW5ob3MsMykNCg0KYGBgDQoNCk9ic2VydmEtc2UgcXVlOg0KDQoqIE8gY2FtcG8gYGFjdWNhcl9yZXNpZHVhbGAgZSBgZnNkYCBwb3NzdWVtIHVtIGRlc3ZpbyBwYWRyw6NvIGFjaW1hIGRhcyBkZW1haXMgdmFyaWF2ZWlzDQoqIEEgbWFpb3JpYSBkb3MgaGlzdG9ncmFtYXMgYXByZXNlbnRhIHVtYSBkaXN0cmlidWnDp8OjbyBub3JtYWwgZW50cmV0YW50byBuw6NvIGNlbnRyYWxpemFkbyBvIHF1ZSBwb2RlIGluZGljYXIgYSBwcmVzZW7Dp2EgZGUgb3V0bGllcnMNCg0KDQoNCiMjIyBWZXJpZmljYW5kbyB2YWxvcmVzIG51bG9zDQoNCmBgYHtyfQ0Kc2FwcGx5KHZpbmhvcywgZnVuY3Rpb24oeClhbGwoaXMubmEoeCkpKQ0KYGBgYA0KDQpPIHJlc3VsdGFkbyBhY2ltYSBub3MgZGVzY3JldmUgcXVlIG7Do28gaMOhIHByZXNlbsOnYSBkZSBudWxvcyBuYSBiYXNlLCBpc3RvIMOpIGluZGljYWRvIHBlbG8gcmV0b3JubyBgRkFMU0VgIGVtIGNhZGEgdmFyacOhdmVsDQoNCg0KYGBge3J9DQoNClJvdHVsb3NfQ29sdW5hcyA8LWMoImlkIiwiYWNpZGV6X2ZpeGEiLCJhY2lkZXogdm9sYXRpbCIJLCJhY2lkbyBjaXRyaWNvIiwiYWN1Y2FyIHJlc2lkdWFsIiwiY2xvcmV0b3MiLCJmc2QiLCJ0c2QiLCJkZW5zaWRhZGUiLAkJCQ0KICAgICAgICAgICAgICAgICAgICAiUEgiLCJzdWxmYXRvcyIsImdyYXUgYWxjb2xpY28iLCJxdWFsaWRhZGUiLCJ0aXBvIikNCg0KZ3JhZmljb19saXN0YSA8LSB2ZWN0b3IoImxpc3QiLCBsZW5ndGggPSBsZW5ndGgoUm90dWxvc19Db2x1bmFzKS0yKQ0KDQpmb3IoaSBpbiAyOjEzKXsNCiAgZ3JhZmljb19saXN0YVtbaS0xXV0gPC0gcGxvdF9seSh4ID0gYXMuZm9ybXVsYSh2aW5ob3NbaV0pLCAgIHR5cGUgPSAnaGlzdG9ncmFtJywgbmFtZSA9IFJvdHVsb3NfQ29sdW5hc1tpXSkNCn0gIA0Kc3VicGxvdChncmFmaWNvX2xpc3RhLCAgbnJvd3MgPSA0KQ0KDQoNCmBgYA0KDQoNCg0KUG9kZW1vcyBvYnNlcnZhciBxdWUgYXBlc2FyIGRvIGRlc2VuaG8gc2VyIHNpbWlsYXIgw6AgdW1hIGRpc3RyaWJ1acOnw6NvIG5vcm1hbCwgaXNzbyBzZSBkZXUgcG9pcyBtYWlzIMOgIGVzcXVlcmRhIGV4Y2V0byBncmF1IGFsY29vbGljbywgcXVlIHNlIHNhYmUNCnF1ZSBuw6NvIGjDoSB2aW5ob3MgY29tIHRlb3IgYWxjb29saWNvIGFiYWl4byBkZSA2LjUlIChsZXZlbmRvIGVtIGNvbnNpZGVyYcOnw6NvIHVtIHZpbmhvIGRlIHNvYnJlbWVzYSBtYWlzIGxpY29yb3NvKS4gcG9ydGFudG8gbm9zc28gcHJveGltbyBvYmpldG8gZGUNCmVzdHVkbyBzZXLDoSBvIGdyYXUgYWxjb29saWNvIGEgcHJvY3VyYSBkZSBvdXRsaWVycyBlIGEgcmVtb8Onw6NvIGRvcyBtZXNtb3MuDQoNCg0KDQoNCg0KDQoNCg0KTyBjb21hbmRvIGFwbGljYWRvIHBhcmEgdG9kb3MgYXRyaWJ1dG9zIGFiYWl4byBleGliacOnw6NvIGRvcyBib3gtcGxvdCBhYmFpeG8gZm9pOiA8YnIgLz4NCg0KPiAqYm94cGxvdChDb2x1bW5fTmFtZSwgY29sPSJzbGF0ZWdyYXkyIiwgcGNoPTE5KSAqICA8YnIgLz4NCj4gKm10ZXh0KCJUaXR1bG8iICwgY2V4PTAuOCwgc2lkZT0xLCBsaW5lPTIpKg0KDQpgYGB7ciwgLCBlY2hvPUZBTFNFfQ0KDQpwYXIobWZyb3c9YygxLDYpLCBvbWEgPSBjKDEsMSwwLDApICsgMC4xLCAgbWFyID0gYygzLDMsMSwxKSArIDAuMSkNCiAgYm94cGxvdChhY2lkZXpfZml4YSwgY29sPSJzbGF0ZWdyYXkyIiwgcGNoPTE5KQ0KICBtdGV4dCgiQWNpZGV6IEZpeGEiICwgY2V4PTAuOCwgc2lkZT0xLCBsaW5lPTIpDQogIGJveHBsb3QoYWNpZGV6X3ZvbGF0aWwsIGNvbD0ic2xhdGVncmF5MiIsIHBjaD0xOSkNCiAgbXRleHQoIkFjaWRleiBWb2xhdGlsIiwgY2V4PTAuOCwgc2lkZT0xLCBsaW5lPTIpDQogIGJveHBsb3QoYWNpZG9fY2l0cmljbywgY29sPSJzbGF0ZWdyYXkyIiwgcGNoPTE5KQ0KICBtdGV4dCgiYWNpZG9fY2l0cmljbyIsIGNleD0wLjgsIHNpZGU9MSwgbGluZT0yKQ0KICBib3hwbG90KGFjdWNhcl9yZXNpZHVhbCwgY29sPSJzbGF0ZWdyYXkyIiwgcGNoPTE5KQ0KICBtdGV4dCgiYWN1Y2FyX3Jlc2lkdWFsIiwgY2V4PTAuOCwgc2lkZT0xLCBsaW5lPTIpDQogIGJveHBsb3QoY2xvcmV0b3MsIGNvbD0ic2xhdGVncmF5MiIsIHBjaD0xOSkNCiAgbXRleHQoImNsb3JldG9zIiwgY2V4PTAuOCwgc2lkZT0xLCBsaW5lPTIpDQogIGJveHBsb3QoZnNkLCBjb2w9InNsYXRlZ3JheTIiLCBwY2g9MTkpDQogIG10ZXh0KCJmc2QiLCBjZXg9MC44LCBzaWRlPTEsIGxpbmU9MikNCiAgDQoNCmBgYA0KDQoNCg0KYGBge3IsICwgZWNobz1GQUxTRX0NCg0KcGFyKG1mcm93PWMoMSw1KSwgb21hID0gYygxLDEsMCwwKSArIDAuMSwgIG1hciA9IGMoMywzLDEsMSkgKyAwLjEpDQogIGJveHBsb3QodHNkLCBjb2w9InNsYXRlZ3JheTIiLCBwY2g9MTkpDQogIG10ZXh0KCJ0c2QiICwgY2V4PTAuOCwgc2lkZT0xLCBsaW5lPTIpDQogIGJveHBsb3QoZGVuc2lkYWRlLCBjb2w9InNsYXRlZ3JheTIiLCBwY2g9MTkpDQogIG10ZXh0KCJkZW5zaWRhZGUiLCBjZXg9MC44LCBzaWRlPTEsIGxpbmU9MikNCiAgYm94cGxvdChQSCwgY29sPSJzbGF0ZWdyYXkyIiwgcGNoPTE5KQ0KICBtdGV4dCgiUEgiLCBjZXg9MC44LCBzaWRlPTEsIGxpbmU9MikNCiAgYm94cGxvdChzdWxmYXRvcywgY29sPSJzbGF0ZWdyYXkyIiwgcGNoPTE5KQ0KICBtdGV4dCgic3VsZmF0b3MiLCBjZXg9MC44LCBzaWRlPTEsIGxpbmU9MikNCiAgYm94cGxvdChncmF1X2FsY29saWNvLCBjb2w9InNsYXRlZ3JheTIiLCBwY2g9MTkpDQogIG10ZXh0KCJncmF1X2FsY29saWNvIiwgY2V4PTAuOCwgc2lkZT0xLCBsaW5lPTIpDQogIA0KYGBgDQoNCiMjIyAqKk91dGxpZXJzKioNCg0KTm90YSBzZSBxdWUgcXVhc2UgIHRvZGFzIGFzIHZhcmnDoXZlaXMgcG9zc3VlbSBvdXRsaWVycyBlIHBhcmEgdW1hIG1lbGhvciBhY3Vyw6FjaWEgbm8gbW9kZWxvIGlyZW1vcyByZW1vdsOqLWxhcyBkYSBhbsOhbGlzZS4NCk8gTWV0b2RvIG1haXMgaW5kaWNhZG8gcGFyYSByZW1vw6fDo28gZG9zIG91dGxpZXJzIMOpIGFtcGxpdHVkZSBpbnRlcnF1YXJ0aWwgKElRUiAtIEludGVyUXVhbnRpbGUgUmFuZ2UpIG9uZGU6DQogICpJUVIgID0gUTMocXVhcnRpbCAzKSAtIFExKHF1YXJ0aWwgMSkNCkNvbSBvIElRUiBjYWxjdWxhZG8gw6kgbmVjZXNzw6FyaW8gZGVmaW5pciBvIGxpbWl0ZSBpbmZlcmlvciBlIHN1cGVyaW9yIHF1ZSDDqSBkYWRvIHBlbGEgc2VndWludGUgZm9ybXVsYToNCg0KICAkJExpbV97U3VwfSA9IFxiYXJ7WH0gKyAxLDUgICogSVFSJCQNCiAgDQogICQkTGltX3tJbmZ9ID0gXGJhcntYfSAtIDEsNSAgKiBJUVIkJA0KDQpQYXJhIGVsdWNpZGFyIGEgYXBsaWNhw6fDo28gZG8gbcOpdG9kbyB2YW1vcyBhbmFsaXNhciBhIHZhcmlhdmVsICoqIkFjaWRleiBGaXhhIioqIG5vdGFtb3MgcXVlIGjDoSBtdWl0b3MgdmFsb3JlcyBhY2ltYSBkbyBRMyBhIHVucyBwb3Vjb3MgYWJhaXhvIGRlIFExLCBPc2VydmUgbyBzdW3DoXJpbyBkZXN0YSB2YXJpYXZlbA0KDQpgYGB7ciB9DQoNCiAgc2tpbShhY2lkZXpfZml4YSkNCg0KICAjZGFkbyBwMjUoUTEpID0gNi40IGUgcDc1KFEzKSA9IDcuNyB0ZW1vczoNCiAgSVFSX0FjaWRlel9Wb2xhdGlsID03LjcgLSA2LjQNCiAgDQogICNjb21vIHJlc3VsdGFkbyB0ZW1vcyAxLjMgDQogICNjb20gaXNzbyBwb2RlbW9zIGRlZmluaXIgb3MgbGltaXRlcyBzdXBlcmlvciBlIGluZmVyaW9yIGRvIHJhbmdlDQogIA0KICBMU19hY2lkZXpfZml4YSA9IDcuNyArICAxLjUgKiBJUVJfQWNpZGV6X1ZvbGF0aWwNCiAgTElfYWNpZGV6X2ZpeGEgPSA2LjQgLSAoMS41ICogSVFSX0FjaWRlel9Wb2xhdGlsKQ0KICANCiAgI3RlbW9zIHVtIGxpbWl0ZSBzdXBlcmlvciBkZSAtMC4wMjUgZSBpbmZlcmlvciBkZSAwLjY1NSBvbmRlIGFzIG9ic2VydmHDp8O1ZXMgYWNpbWEgb3UgYWJhaXhvIGRlc3NlcyBmYXRvcmVzIHNlcsOjbyBjb25zaWRlcmFkYXMgb3V0aWxlcnMNCiAgI2NvbSBiYXNlIG5vcyBsaW1pdGVzIGVuY29udHJhZG9zIGZhcmVpIHVtIHN1YiBzZXQgZG8gY29uanVudG8gb3JpZ2kgbmFsIGRlIGRhZG9zIGxldmFuZG8gZW0gY29uc2lkZXJhY2FvIG9zIGxpbWl0ZXMgZW5jb250cmFkb3MNCiAgVmluaG9zX05vcm1hbGl6YWRvIDwtZmlsdGVyKHZpbmhvcywgYWNpZGV6X2ZpeGEgPj0gTElfYWNpZGV6X2ZpeGEgJiBhY2lkZXpfZml4YSA8PSBMU19hY2lkZXpfZml4YSkNCiAgDQogICNjb21wYXJhbmRvIG9zIHJlc3VsdGFkb3MNCiAgcGFyKG1mcm93PWMoMSwyKSwgb21hID0gYygxLDEsMCwwKSArIDAuMSwgIG1hciA9IGMoMywzLDEsMSkgKyAwLjEpDQogICAgYm94cGxvdChhY2lkZXpfZml4YSwgY29sPSJzbGF0ZWdyYXkyIiwgcGNoPTE5KQ0KICAgIG10ZXh0KCJBbnRlcyIgLCBjZXg9MC44LCBzaWRlPTEsIGxpbmU9MikNCiAgICBib3hwbG90KFZpbmhvc19Ob3JtYWxpemFkbyRhY2lkZXpfZml4YSwgY29sPSJzbGF0ZWdyYXkyIiwgcGNoPTE5KQ0KICAgIG10ZXh0KCJEZXBvaXMiICwgY2V4PTAuOCwgc2lkZT0xLCBsaW5lPTIpDQoNCmBgYA0KDQpEZSBtb2RvIHF1ZSBhIHJlbW/Dp8OjbyBkb3Mgb3V0bGllcnMgZmV6IGNvbSBxdWUgYSBkaXN0cmlidWnDp8OjbyBkb3MgZGFkb3MgZmljYXNzZSBtYWlzIGhvbW9nw6puZWEgY29tbyBkZW1vbnN0cm8gbm9zIGhpc3Ryb2dyYW1hcyBhIHNlZ3Vpcg0KDQpgYGB7ciB9DQoNCiAgI2NvbXBhcmFuZG8gb3MgcmVzdWx0YWRvcw0KICBwYXIobWZyb3c9YygxLDIpLCBvbWEgPSBjKDEsMSwwLDApICsgMC4xLCAgbWFyID0gYygzLDMsMSwxKSArIDAuMSkNCiAgICBoaXN0KGFjaWRlel9maXhhLCBjb2w9InNsYXRlZ3JheTIiLCBtYWluID0gIiIpDQogICAgbXRleHQoIkFudGVzIiAsIGNleD0wLjgsIHNpZGU9MSwgbGluZT0yKQ0KICAgIGhpc3QoVmluaG9zX05vcm1hbGl6YWRvJGFjaWRlel9maXhhLCBjb2w9InNsYXRlZ3JheTIiLCBtYWluID0gIiIpDQogICAgbXRleHQoIkRlcG9pcyIgLCBjZXg9MC44LCBzaWRlPTEsIGxpbmU9MikNCg0KYGBgDQoNCg0KUGFyYSBhdXRvbWF0aXphciBvIHByb2Nlc3NvIGRlIGFuYWxpc2UgZSByZW1vw6fDo28gZG9zIG91dGxpZXJzIGNyaWFtb3MgdW1hIGZ1bsOnw6NvIHBhcmEgZXhlY3V0YXIgZXNzYSB0YXJlZmEsIGUgc2VndWU6DQoNCmBgYHtyICwgcmVzdWx0cz0iaGlkZSJ9DQoNCg0KDQoNCiNjcmlhbmRvIHVtYSBmdW5jYW8gcGFyYSByZW1vdmVyIG9zIG91dGxpZXJzIGRhcyBjb2x1bmFzIA0KcmVtb3ZlX291dGxpZXJzIDwtIGZ1bmN0aW9uKHgsIG5hLnJtID0gVFJVRSwgLi4uKSB7DQogIHFudCA8LSBxdWFudGlsZSh4LCBwcm9icz1jKC4yNSwgLjc1KSwgbmEucm0gPSBuYS5ybSwgLi4uKQ0KICBIIDwtIDEuNSAqIElRUih4LCBuYS5ybSA9IG5hLnJtKQ0KICB5IDwtIHgNCiAgeVt4IDwgKHFudFsxXSAtIEgpXSA8LSBOQQ0KICB5W3ggPiAocW50WzJdICsgSCldIDwtIE5BDQogIHkNCn0NCg0KdmluaG9zJGFjaWRlel9maXhhIDwtIHJlbW92ZV9vdXRsaWVycyhhY2lkZXpfZml4YSwgVCkNCnZpbmhvcyRhY2lkZXpfdm9sYXRpbCA8LSByZW1vdmVfb3V0bGllcnMoYWNpZGV6X3ZvbGF0aWwpDQp2aW5ob3MkYWNpZG9fY2l0cmljbyA8LSByZW1vdmVfb3V0bGllcnMoYWNpZG9fY2l0cmljbywgVCkNCnZpbmhvcyRhY3VjYXJfcmVzaWR1YWwgPC0gcmVtb3ZlX291dGxpZXJzKGFjdWNhcl9yZXNpZHVhbCwgVCkNCnZpbmhvcyRjbG9yZXRvcyA8LSByZW1vdmVfb3V0bGllcnMoY2xvcmV0b3MsIFQpDQp2aW5ob3MkZnNkIDwtIHJlbW92ZV9vdXRsaWVycyhmc2QsIFQpDQp2aW5ob3MkdHNkIDwtIHJlbW92ZV9vdXRsaWVycyh0c2QsIFQpDQp2aW5ob3MkZGVuc2lkYWRlIDwtIHJlbW92ZV9vdXRsaWVycyhkZW5zaWRhZGUsIFQpDQp2aW5ob3MkUEggPC0gcmVtb3ZlX291dGxpZXJzKFBILCBUKQ0KdmluaG9zJHN1bGZhdG9zIDwtIHJlbW92ZV9vdXRsaWVycyhzdWxmYXRvcywgVCkNCnZpbmhvcyRncmF1X2FsY29saWNvIDwtIHJlbW92ZV9vdXRsaWVycyhncmF1X2FsY29saWNvLCBUKQ0KdmluaG9zJHF1YWxpZGFkZSA8LSByZW1vdmVfb3V0bGllcnMocXVhbGlkYWRlLCBUKQ0KDQpgYGANCg0KRXhhbWluYW5kbyBvcyBkYWRvcyBwb3MgbGltcGV6YSBkb3Mgb3V0bGllcnMNCg0KYGBge3J9DQoNCg0KDQogIA0KYGBgDQo=